
#include "Ring.h"
#include "BoundingBox.h"
#include "HitRecord.h"
#include "Point.h"
#include "Ray.h"
#include "Vector.h"
#include <math.h>
#include <iostream>
#include <fstream>
using namespace std;
Ring::Ring(Material* material, const Point& center, const Vector& normal, double radius1, double radius2)
  : Primitive(material), center(center), my_normal(normal)
{
	my_normal.normalize();
  d = Dot(my_normal, Vector(center));
  if(radius1 > radius2)
  {
	  outer_radius = radius1;
	  inner_radius = radius2;
  } else {
	  outer_radius = radius2;
	  inner_radius = radius1;
  }
}

Ring::~Ring()
{
}

void Ring::getBounds(BoundingBox& bbox) const
{
  Vector diag(outer_radius, outer_radius, outer_radius);
  bbox.extend(center+diag);
  bbox.extend(center-diag);
}

void Ring::intersect(HitRecord& hit, const RenderContext&, const Ray& ray) const
{
	double result = DBL_MAX;
	//determine the distance from the ray to the intersection
	double denominator = Dot(my_normal, ray.direction());
	if(abs(denominator) > EPSILON)
	{
		double t = (d - Dot(my_normal, Point::Point(ray.origin()))) / denominator;
		Point intersection = ray.origin() + ray.direction() * t;
		Vector r = intersection - center;
		if(r.length() < outer_radius && r.length() > inner_radius)
			if(t < result && t > EPSILON)
				hit.hit(t, this, matl);
	}
	return;
		
}

void Ring::normal(Vector& normal, const RenderContext&, const Point& hitpos,
                    const Ray& ray, const HitRecord& hit) const
{
  normal = my_normal;
}
